﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Collections.ObjectModel;
using System.Collections;

namespace CitrixPVSWrapper
{

    [System.Management.Automation.Cmdlet("RunWithReturn", "PvsStoreFreeSpace", SupportsShouldProcess = true)]
    public class Run_PvsStoreFreeSpace : System.Management.Automation.PSCmdlet
    {

        [Parameter(ParameterSetName = "Store", Mandatory = true)]
        public PvsStore Store;

        [Parameter(ParameterSetName = "StoreId", ValueFromPipelineByPropertyName = true, Mandatory = true)]
        public string StoreId;

        [Parameter(ParameterSetName = "StoreName", Mandatory = true)]
        public string StoreName;
        
        [Parameter(Mandatory = false)]
        public PvsSite Site;

        [Parameter(Mandatory = false)]
        public string SiteId;

        [Parameter(Mandatory = false)]
        public string SiteName;

        [Parameter(Mandatory = false)]
        public PvsServer Server;

        [Parameter(Mandatory = false)]
        public string ServerId;

        [Parameter(Mandatory = false)]
        public string ServerName;

        protected override void BeginProcessing()
        {
            // Test for mutually exclusive parameters
            Validate.MutuallyExclusiveParameters(this.MyInvocation.BoundParameters, new string[] { "Server", "ServerId", "ServerName" }, false);
            Validate.MutuallyExclusiveParameters(this.MyInvocation.BoundParameters, new string[] { "Site", "SiteId", "SiteName" }, false);
        }

        protected override void ProcessRecord()
        {
            // Verbose and Debug Settings
            Boolean Verbose = this.MyInvocation.BoundParameters.ContainsKey("Verbose");
            WriteVerbose("Verbose Flag: " + Verbose);
            Boolean Debug = this.MyInvocation.BoundParameters.ContainsKey("Debug");
            WriteDebug("Debug Flag: " + Debug);

            // Collections to hold the queries and the results
            Collection<QueryDefinition> RunQueries = new Collection<QueryDefinition>();
            string TargetObject = "StoreFreeSpace";

            // Build the queries based on the parameter sets
            switch (this.ParameterSetName)
            {

                case "Store":
                    {
                        RunQueries.Add(new QueryDefinition(QueryActionType.RunWithReturn, TargetObject, "StoreId=\"" + this.Store.StoreId + "\""));
                        break;
                    }

                case "StoreId":
                    {
                        RunQueries.Add(new QueryDefinition(QueryActionType.RunWithReturn, TargetObject, "StoreId=\"" + this.StoreId + "\""));
                        break;
                    }

                case "StoreName":
                    {
                        foreach (PvsStore QryStore in Get_PvsStore_Internal.Get_StoreByName(this.StoreName, Verbose))
                        { RunQueries.Add(new QueryDefinition(QueryActionType.RunWithReturn, TargetObject, "StoreId=\"" + QryStore.StoreId + "\"")); }
                        break;
                    }

            }

            // Test that we have a suitable object to perform the Run with, and build the confirmation message
            if (RunQueries.Count() == 0)
            {
                WriteError(new ErrorRecord(new InvalidOperationException("No items were found to check for free space on using the supplied parameters"), "1", ErrorCategory.InvalidArgument, null));
            }

            // Execute the run queries
            foreach (QueryDefinition RunQuery in RunQueries)
            {

                // Add in the optional parameters
                if (MyInvocation.BoundParameters.ContainsKey("Server")) { RunQuery.Parameters.Add("serverId=\"" + this.Server.ServerId + "\""); }
                if (MyInvocation.BoundParameters.ContainsKey("ServerId")) { RunQuery.Parameters.Add("serverId=\"" + this.ServerId + "\""); }
                if (MyInvocation.BoundParameters.ContainsKey("ServerName")) { RunQuery.Parameters.Add("serverName=\"" + this.ServerName + "\""); }
                if (MyInvocation.BoundParameters.ContainsKey("Site")) { RunQuery.Parameters.Add("SiteId=\"" + this.Site.SiteId + "\""); }
                if (MyInvocation.BoundParameters.ContainsKey("SiteId")) { RunQuery.Parameters.Add("SiteId=\"" + this.SiteId + "\""); }
                if (MyInvocation.BoundParameters.ContainsKey("SiteName")) { RunQuery.Parameters.Add("SiteName=\"" + this.SiteName + "\""); }

                string objectId;
                string objectName;
                string ShouldProcessMessage;

                // Check that we have a valid parameter to work with, extract the object id/name and build the ShouldProcess message
                if (RunQuery.Parameters.Where(p => p.StartsWith("StoreId")).Count() == 1)
                {
                    objectId = RunQuery.Parameters.Where(p => p.StartsWith("StoreId")).First().Split('=')[1].Replace('"', ' ').Trim();
                    if (Get_PvsStore_Internal.Get_StoreById(objectId).Count() != 1)
                    {
                        WriteError(new ErrorRecord(new InvalidOperationException(String.Format("Store Id {0} does not exist", objectId)), "2", ErrorCategory.InvalidArgument, null));
                        continue;
                    }
                    objectName = Get_PvsStore_Internal.Get_StoreById(objectId).First().StoreName;
                    ShouldProcessMessage = String.Format("Check for free space on store {0} with store Id {1}", objectName, objectId);
                }

                else
                {
                    WriteError(new ErrorRecord(new InvalidOperationException("Query does not contain any valid targets"), "2", ErrorCategory.InvalidArgument, null));
                    continue;
                }

                // Perform the actual run and return any errors
                if (ShouldProcess(ShouldProcessMessage))
                {
                    foreach (string[] Record in PvsHelpers.ExecuteMcliQuery(RunQuery, Verbose, Debug))
                    {
                        WriteDebug("Returning Object");
                        WriteObject(PvsHelpers.Get_UInt32ValueFromRecord("FreeSpaceMb", Record, Verbose));
                    }
                }

            }
        }
    }
}
